home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource5 / 363_01 / bitfield.c < prev    next >
C/C++ Source or Header  |  1991-12-16  |  8KB  |  236 lines

  1. /***********************************************************************
  2.  *
  3.  *      BITFIELD Routines for 68020 Assembler
  4.  *      Routines for instructions:
  5.  *          BFCHG       BFEXTS      BFFFO       BFSET
  6.  *          BFCLR       BFEXTU      BFINS       BFTST
  7.  *                      
  8.  *  Function: char *bitFieldParse(char *p, opDescriptor *d, int *errorPtr)
  9.  *      Parses the expression of the format {offset:width}.
  10.  *      p       - pointer to the input string,
  11.  *      d       - pointer to the operation descriptor structure,
  12.  *      errorPtr - pointer to the error flag.
  13.  *
  14.  *      Offset and width, together with the offset and width format (data
  15.  *      register or immediate), are returned in the bfXtenWord member of the
  16.  *      opDescriptor struct (d->bfXtenWord),
  17.  *      error status is returned in errorPtr via the standard mechanism.
  18.  *      
  19.  *  Function: int bitField(instruction *tablePtr, int size, char *label,
  20.  *                                                  char *op, int *errorPtr)
  21.  *      Builds BFxxx instructions.
  22.  *      tablePtr - pointer to the instruction table,
  23.  *      size      - not used. Included for compatibility with the opDescriptor
  24.  *                  struct definition.
  25.  *      label    - pointer to the label string, empty string if no label
  26.  *      op       - pointer to the input string,
  27.  *      errorPtr - pointer to the error flag.
  28.  *      The routine returns an error code in *errorPtr using the standard
  29.  *      mechanism. 
  30.  *
  31.  *      Version 1.0
  32.  *      Author: Andrew E. Romer
  33.  *      38 Bolsover Road, Worthing, West Sussex, England BN13 1NT.
  34.  *
  35.  *      Date: May 1991
  36.  *
  37.  ***********************************************************************/
  38.  
  39.  
  40. #include <stdio.h>
  41. #include <ctype.h>
  42. #include "asm.h"
  43.  
  44. extern long loc;
  45. extern char pass2;
  46.  
  47. /* extension word fields */
  48. #define     REG_OFFSET      0x800       /* bit 11 set indicates that offset
  49.                                          * is contained in the data register
  50.                                          * specified in bits 12-14 */
  51. #define     OFFSET(x)       (x) << 6    /* offset field */
  52. #define     REG_WIDTH       0x20        /* bit 5 set indicates that width
  53.                                          * is contained in the data register
  54.                                          * specified in bits 0-2. */
  55.  
  56.  
  57. #define isRegNum(c) ((c >= '0') && (c <= '7'))
  58.  
  59.  
  60. char *bitFieldParse(char *p, opDescriptor *d, int *errorPtr)
  61.     {
  62.     long value;                 /* temporary store */
  63.  
  64. /* Parse offset */
  65.     if (p[0] == '{')
  66.                             /* dummy comment to enable '}' bracket pairing */
  67.         {
  68.         if (p[1] == 'D' && isRegNum(p[2]) && p[3] == ':')
  69.                         /* Offset is specified in a data register (d0 - d7) */
  70.             {
  71.             d->bfXtenWord |= REG_OFFSET | OFFSET(p[2] - '0');
  72.             p += 3;                 /* point to fields' separator ':' */
  73.             } 
  74.         else
  75.                             /* Offset is an immediate operand */
  76.             {
  77.             p = eval(++p, &value, &d->backRef, errorPtr);
  78.                 if (*errorPtr > SEVERE)
  79.                     return NULL;
  80.                 else if (p[0] != ':')
  81.                                                     /* missing terminator */
  82.                     {
  83.                     NEWERROR(*errorPtr, SYNTAX);
  84.                     return NULL;
  85.                     }
  86.                 else
  87.                     d->bfXtenWord |= OFFSET(value & 0x1f);
  88.             }
  89.         /* parse width */
  90.                             /*  dummy comment to enable bracket pairing '{' */
  91.         if (p[1] == 'D' && isRegNum(p[2]) && p[3] == '}')
  92.                         /* Width is specified in a data register (d0 - d7) */
  93.             {
  94.             d->bfXtenWord |= REG_WIDTH | (p[2] - '0');
  95.             return p+4;     /* point beyond the {offset:width} expression */
  96.             }
  97.         else 
  98.                             /* Width is an immediate operand */
  99.             {
  100.             p = eval(++p, &value, &d->backRef, errorPtr);
  101.                 if (*errorPtr > SEVERE)
  102.                     return NULL;
  103.                             /*  dummy comment to enable '{' bracket pairing */
  104.                 else if (p[0] != '}')
  105.                                                     /* missing terminator */
  106.                     {
  107.                     NEWERROR(*errorPtr, SYNTAX);
  108.                     return NULL;
  109.                     }
  110.                 else
  111.                     d->bfXtenWord |= value & 0x1f;
  112.             return p+1;     /* point beyond the {offset:width} expression */
  113.             }
  114.         }
  115.     }
  116.  
  117. int bitField(instruction *tablePtr, int size, char *label, char *op,
  118.                                                             int *errorPtr)
  119.     {
  120.     variant *variantPtr;
  121.     opDescriptor source, dest;
  122.     unsigned short mask, i;
  123.  
  124.  
  125. /* op points to the first character of the operand field */
  126.  
  127. /* Move location counter to a word boundary and fix the listing before
  128.  * assembling the instruction */
  129.  
  130.     if (loc & 1)                         /* if not at word boundary */
  131.         {
  132.         loc++;
  133.         listLoc();
  134.         }
  135.  
  136.     if (*label)
  137.         {
  138.         create(label, loc, errorPtr);
  139.         if (*errorPtr > SEVERE)
  140.             return NORMAL;
  141.         }
  142.  
  143.     variantPtr = tablePtr->variantPtr;
  144.     source.bfXtenWord = 0;
  145.     dest.bfXtenWord = 0;
  146.  
  147. /* Parse source */
  148.     op = opParse(op, &source, errorPtr);
  149.     if (*errorPtr > SEVERE)
  150.         return NORMAL;
  151.  
  152. /* Verify source address mode */
  153.     if ((source.mode & variantPtr->source) == 0)
  154.         {
  155.         NEWERROR(*errorPtr, INV_ADDR_MODE);
  156.         return NULL;
  157.         }
  158. /* Parse source */
  159.     if ((variantPtr->source == (DnDirect | CtrAlt))
  160.                         || (variantPtr->source == (DnDirect | Control)))
  161.         {
  162.         op = bitFieldParse(op, &source, errorPtr);
  163.         if(*errorPtr > SEVERE)
  164.             return NORMAL;
  165.         }
  166.     else                                /* variantPtr->source == DnDirect */
  167.         dest.bfXtenWord |= source.reg << 12;
  168.  
  169. /* Parse destination if required */
  170.     if (variantPtr->dest)
  171.         {
  172.         if (*op != ',')
  173.             {
  174.             NEWERROR(*errorPtr, SYNTAX);
  175.             return NORMAL;
  176.             }
  177.         op = opParse(op+1, &dest, errorPtr);
  178.         if (*errorPtr > SEVERE)
  179.             return NORMAL;
  180.  
  181. /* Verify address mode */
  182.         if ((dest.mode & variantPtr->dest) == 0)
  183.             {
  184.             NEWERROR(*errorPtr, INV_ADDR_MODE);
  185.             return NULL;
  186.             }
  187.         else                            /* variantPtr->dest == DnDirect */
  188.             source.bfXtenWord |= dest.reg << 12;
  189.  
  190.         if (variantPtr->dest == (DnDirect | Control))
  191.             {
  192.             op = bitFieldParse(op, &dest, errorPtr);
  193.             if(*errorPtr > SEVERE)
  194.                 return NORMAL;
  195.             }
  196.         }
  197.  
  198.     if (!isspace(*op) && *op != '\0')       /* if operand field contains
  199.                                              * superfluous characters */
  200.         {
  201.         NEWERROR(*errorPtr, SYNTAX);
  202.         return NORMAL;
  203.         }
  204.     mask = variantPtr -> wordmask;
  205.  
  206. /* Generate the instruction */
  207.     if ((variantPtr->source == (DnDirect | CtrAlt))
  208.                     || (variantPtr->source == (DnDirect | Control)))
  209.         {
  210.         if (pass2)
  211.             output( (long) (mask | effAddr(&source)), WORD);
  212.         loc += 2;
  213.         if (pass2)
  214.             output(source.bfXtenWord, WORD);
  215.         loc += 2;
  216.         extWords(&source, WORD, errorPtr);
  217.         if (variantPtr->dest)
  218.             extWords(&dest, WORD, errorPtr); 
  219.         return NORMAL;
  220.         }
  221.     else                    /* wariantPtr->source must be DnDirect and
  222.                              * variantPtr->dest - DnDirect or Control */
  223.         {
  224.         if (pass2)
  225.             output( (long) (mask | effAddr(&dest)), WORD);
  226.         loc += 2;
  227.         if (pass2)
  228.             output(dest.bfXtenWord, WORD);
  229.         loc += 2;
  230.         extWords(&source, WORD, errorPtr);
  231.         extWords(&dest, WORD, errorPtr);
  232.         return NORMAL;
  233.         }
  234.     return NORMAL;
  235.     }
  236.